﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.UI;

namespace WebStudio.Mvc.Core.Extensions
{
    /// <summary>
    /// GridView扩展
    /// </summary>
    public static class GridViewExtension
    {
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="helper"></param>
        /// <param name="data"></param>
        /// <param name="columns"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public static string GridView<T>(this HtmlHelper helper, object data, string[] columns, GridViewOption options)
        {

            var items = (IEnumerable<T>)data;
            if (items == null)
            {
                items = (IEnumerable<T>)helper.ViewData.Model;
            }
            if (columns == null)
            {
                columns = typeof(T).GetProperties().Select(p => p.Name).ToArray();
            }
            var writer = new HtmlTextWriter(new StringWriter());
            writer.RenderBeginTag(HtmlTextWriterTag.Table);
            writer.RenderBeginTag(HtmlTextWriterTag.Thead);
            //string identityColumnName = ((PaginatedList<T>)items).OrderByColumnName;
            //string sorttype = ((PaginatedList<T>)items).SortType;
            string identityColumnName = "StartDate";
            string sorttype = "";

            RenderHeader(helper, writer, columns, options, sorttype);
            writer.RenderEndTag();
            foreach (var item in items)
            {
                RenderRow<T>(helper, writer, columns, item, identityColumnName, options);
            }
            writer.RenderEndTag();
            RenderPageList<T>(helper, writer, (PaginatedList<T>)items, columns);
            writer.RenderEndTag();
            return writer.InnerWriter.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="writer"></param>
        /// <param name="columns"></param>
        /// <param name="options"></param>
        /// <param name="sorttype"></param>
        public static void RenderHeader(HtmlHelper helper, HtmlTextWriter writer, string[] columns, GridViewOption options, string sorttype)
        {
            if (("asc").Equals(sorttype))
            {
                sorttype = "desc";
            }
            else
            {
                sorttype = "asc";
            }
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            int i = 0;
            foreach (var columnName in columns)
            {
                writer.RenderBeginTag(HtmlTextWriterTag.Th);
                var currentAction = (string)helper.ViewContext.RouteData.Values["action"];
                string link = null;
                if (options.Columns == null)
                {
                    link = helper.ActionLink(columnName, currentAction, new { orderby = columnName, sort = sorttype }).ToString();
                }
                else
                {
                    link = helper.ActionLink(options.Columns[i], currentAction, new { orderby = columnName, sort = sorttype }).ToString();
                    i++;
                }
                writer.Write(link);
                writer.RenderEndTag();
            }
            // Show edit column?
            bool showEditColumn = options.ShowEditButton || options.ShowDeleteButton;
            if (showEditColumn)
            {
                writer.RenderBeginTag(HtmlTextWriterTag.Th);
                writer.Write(options.ManageButtonText);
                writer.RenderEndTag();
            }
            writer.RenderEndTag();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="helper"></param>
        /// <param name="writer"></param>
        /// <param name="columns"></param>
        /// <param name="item"></param>
        /// <param name="identityColumnName"></param>
        /// <param name="options"></param>
        public static void RenderRow<T>(HtmlHelper helper, HtmlTextWriter writer, string[] columns, T item, string identityColumnName, GridViewOption options)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            foreach (var col in columns)
            {
                writer.AddAttribute("class", "grid_" + col.ToString());
                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                var value = typeof(T).GetProperty(col).GetValue(item, null) ?? String.Empty;
                writer.Write(helper.Encode(value.ToString()));
                writer.RenderEndTag();
            }
            // Show edit column?
            bool showEditColumn = options.ShowEditButton || options.ShowDeleteButton;

            if (showEditColumn)
            {
                var identityVaule = typeof(T).GetProperty(identityColumnName).GetValue(item, null);
                writer.RenderBeginTag(HtmlTextWriterTag.Td);

                if (options.ShowEditButton)
                {
                    var link = helper.ActionLink(options.EditButtonText, options.EditAction, new { id = identityVaule });
                    writer.Write(link);
                    writer.Write(" ");
                }

                if (options.ShowDeleteButton)
                {
                    var link = helper.ActionLink(options.DeleteButtonText, options.DeleteAction, new { id = identityVaule });
                    writer.Write(link);
                }

                writer.RenderEndTag();
            }
            writer.RenderEndTag();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="helper"></param>
        /// <param name="writer"></param>
        /// <param name="items"></param>
        /// <param name="columns"></param>
        public static void RenderPageList<T>(HtmlHelper helper, HtmlTextWriter writer, PaginatedList<T> items, string[] columns)
        {
            if (items.TotalPages == 1)
            {
                return;
            }
            var currentAction = (string)helper.ViewContext.RouteData.Values["action"];
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.AddAttribute(HtmlTextWriterAttribute.Colspan, columns.Length.ToString());
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.AddStyleAttribute(HtmlTextWriterStyle.ListStyleType, "none");
            writer.AddAttribute(HtmlTextWriterAttribute.Class, "grid_ul");
            writer.RenderBeginTag(HtmlTextWriterTag.Ul);

            if (items.HasPreviousPage)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Class, "grid_prev");
                writer.RenderBeginTag(HtmlTextWriterTag.Li);
                var link = helper.ActionLink("<<", currentAction, new { page = items.PageIndex - 1 });
                writer.Write(link);
                writer.RenderEndTag();
            }
            //for (var i = 1; i <= items.TotalPages; i++)
            //{
            //    writer.Write("&nbsp;&nbsp;");
            //    var index = i - 1;
            //    if (index == items.PageIndex)
            //    {
            //        writer.Write("<b>" + i.ToString() + "</b>");
            //        continue;
            //    }
            //    var link = helper.ActionLink(i.ToString(), currentAction, new { page = index });
            //    writer.Write(link);
            //}
            int[] listed = new int[10];
            listed[0] = 0;
            listed[1] = 1;
            listed[8] = items.TotalPages - 2;
            listed[9] = items.TotalPages - 1;
            int started = (items.PageIndex - 2) > 2 ? (items.PageIndex - 2) : 2;
            if (items.PageIndex > items.TotalPages - 7)
            {
                started = items.TotalPages - 8;
            }
            for (int i = 2; i < 8; i++)
            {
                listed[i] = started;
                started++;
            }
            if (items.TotalPages < 10)
            {
                for (int i = 0; i < items.TotalPages; i++)
                {
                    listed[i] = i;
                }
                listed[items.TotalPages] = -1;
            }
            foreach (var i in listed)
            {
                if ((items.TotalPages < 10) && i == -1)
                {
                    break;
                }
                if (i == items.PageIndex)
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Id, "grid_li_current");
                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    writer.Write("<b>" + (i + 1).ToString() + "</b>");
                    writer.RenderEndTag();
                    continue;
                }
                var link = helper.ActionLink((i + 1).ToString(), currentAction, new { page = i });
                writer.RenderBeginTag(HtmlTextWriterTag.Li);
                writer.Write(link);
                writer.RenderEndTag();
                if (items.PageIndex > 4 && items.TotalPages > 10 && i == listed[1])
                {
                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    writer.Write("......");
                    writer.RenderEndTag();
                }
                if (items.PageIndex < (items.TotalPages - 6) && items.TotalPages > 10 && i == listed[7])
                {
                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    writer.Write("......");
                    writer.RenderEndTag();
                }

            }
            if (items.HasNextPage)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Class, "grid_next");
                writer.RenderBeginTag(HtmlTextWriterTag.Li);
                var link = helper.ActionLink(">>", currentAction, new { page = items.PageIndex + 1 });
                writer.Write(link);
                writer.RenderEndTag();
            }

            writer.RenderEndTag();
            writer.RenderEndTag();
            writer.RenderEndTag();
            string str = @"<style>" +
                ".grid_ul li{" +
                "float:left;" +
                "margin-left:5px;" +
                "</style>";
            writer.Write(str);
        }
    }

    public class GridViewOption
    {
        private bool showEditButton = true;
        private bool showDeleteButton = true;

        private string editButtonText = "Edit";
        private string deleteButtonText = "Delete";

        private string editAction = "Edit";
        private string deleteAction = "Delete";

        private string manageButtonText = "Manage";

        private string[] columns;
        public bool ShowEditButton
        {
            get { return showEditButton; }
            set { showEditButton = value; }
        }

        public bool ShowDeleteButton
        {
            get { return showDeleteButton; }
            set { showDeleteButton = value; }
        }

        public string EditButtonText
        {
            get { return editButtonText; }
            set { editButtonText = value; }
        }

        public string DeleteButtonText
        {
            get { return deleteButtonText; }
            set { deleteButtonText = value; }
        }

        public string EditAction
        {
            get { return editAction; }
            set { editAction = value; }
        }

        public string DeleteAction
        {
            get { return deleteAction; }
            set { deleteAction = value; }
        }

        public string[] Columns
        {
            get { return columns; }
            set { columns = value; }
        }

        public string ManageButtonText
        {
            get { return manageButtonText; }
            set { manageButtonText = value; }
        }
    }

}
